//
//  CoreUserNetworking.m
//  CoreUser
//
//  Created by Demi on 17/04/2017.
//  Copyright © 2017 Azazie. All rights reserved.
//

#import "CoreUserNetworking.h"

#import <base/base.h>


#if DEBUG || TESTRELEASE
#import <base/DebugManager.h>
#endif

#import <Base64/MF_Base64Additions.h>

@implementation CoreUserNetworking

+ (nullable AccessToken *)fetchAccessTokenFromResponseObject:(nullable id)responseObject
{
    if (!responseObject || ![responseObject isKindOfClass:NSDictionary.class])
    {
        return nil;
    }
    
    NSString *tokenString = [responseObject tx_stringForKey:@"token"];
    if (!tokenString)
    {
        return nil;
    }
    
    NSArray *parts = [tokenString componentsSeparatedByString:@"."];
    if (parts.count < 3)
    {
        return nil;
    }
    
    NSString *payloadPart = parts[1];
    NSData *base64Data = [NSData dataWithBase64UrlEncodedString:payloadPart];
    if (!base64Data)
    {
        return nil;
    }
    
    NSDictionary *payloadJSON = [NSJSONSerialization JSONObjectWithData:base64Data options:0 error:NULL];
    if (!payloadJSON || ![payloadJSON isKindOfClass:NSDictionary.class])
    {
        return nil;
    }
    
    NSNumber *expirationTimeIntervaluNumber = [payloadJSON tx_numberForKey:@"exp"];
    NSNumber *refreshTimeIntervalNumber = [payloadJSON tx_numberForKey:@"iat"];
    NSString *userID = [payloadJSON tx_stringForKey:@"user_id"];
    if (!expirationTimeIntervaluNumber || !refreshTimeIntervalNumber || !userID)
    {
        return nil;
    }
    
    return [[AccessToken alloc] initWithTokenString:tokenString
                                             userID:userID
                                     expirationDate:[NSDate dateWithTimeIntervalSince1970:expirationTimeIntervaluNumber.floatValue] refreshDate:[NSDate dateWithTimeIntervalSince1970:refreshTimeIntervalNumber.floatValue]];
}

+ (RACSignal<AccessToken *> *)handleAccessTokenWithSignal:(RACSignal *)signal is_guest:(int)guest
{
    return [signal tryMap:^id _Nonnull(RACTuple * _Nullable value, NSError * _Nullable __autoreleasing * _Nullable errorPtr) {
        NSDictionary *responseObject = value.second;
        AccessToken *token = [self fetchAccessTokenFromResponseObject:responseObject];
        token.is_guest = guest;
        if (!token)
        {
            if (errorPtr)
            {
                *errorPtr = [NSError errorWithDomain:NSURLErrorDomain
                                                code:NSURLErrorBadServerResponse
                                            userInfo:nil];
            }
        }
        else
        {
            [AccessToken setCurrentAccessToken:token];
        }
        return token;
    }];
}

+ (RACSignal<AccessToken *> *)registerWithEmail:(NSString *)email password:(NSString *)passwd weddingDate:(NSDate *)weddingDate is_guest:(int)guest
{
    NSDateFormatter *df = [[NSDateFormatter alloc] init];
    df.dateFormat = @"yyyy-MM-dd";
    NSMutableDictionary *parameters = [NSMutableDictionary dictionaryWithCapacity:3];
    parameters[@"email"] = email;
    parameters[@"password"] = passwd;
    parameters[@"is_guest"] = @(guest);
    parameters[@"wedding_date"] = [df stringFromDate:weddingDate];
    RACSignal *networkSignal = [APINetwork rac_POST:@"registry" parameters:parameters];
    return [self handleAccessTokenWithSignal:networkSignal is_guest:guest];
}


+ (RACSignal<AccessToken *> *)loginWithEmail:(NSString *)email password:(NSString *)password
{
    if (!email || email.length == 0 || !password || password.length == 0) {
        return RACSignal.empty;
    }
    NSDictionary *parameters = @{@"email": email,
                                 @"password": password};
    
    
    NSString *email1 = @"testetstetst";
    NSString *passwordo = password.copy;
    
    RACSignal *networkSignal = [APINetwork rac_POST:@"login" parameters:parameters];
    return [[self handleAccessTokenWithSignal:networkSignal is_guest:0] doNext:^(AccessToken * _Nullable x) {
#if DEBUG || TESTRELEASE
        [DebugManager registerAccountInfo:email password:password];
#endif
    }];
}

+ (RACSignal *)requestResetPasswordWithEmail:(NSString *)email
{
    NSDictionary *parameters = @{@"email" : email};
    return [APINetwork rac_POST:@"resetpassword" parameters:parameters];
}

+ (RACSignal<AccessToken *> *)loginWithFacebookAccessToken:(NSString *)token
{
    NSDictionary *parameters = @{@"access_token": token};
    RACSignal *networkSignal = [APINetwork rac_POST:@"fb-login" parameters:parameters];
    return [self handleAccessTokenWithSignal:networkSignal is_guest:0];
}

+ (RACSignal<AccessToken *> *)loginWithFacebookAccessToken:(NSString *)token email:(NSString *)email
{
    NSDictionary *parameters = @{@"access_token": token,
                                 @"email": email};
    return [self handleAccessTokenWithSignal:[APINetwork rac_POST:@"fb-login/email" parameters:parameters] is_guest:0];
}

+ (RACSignal<AccessToken *> *)loginWithFacebookAccessToken:(NSString *)token email:(NSString *)email password:(nonnull NSString *)passwd
{
    NSDictionary *parameters = @{@"access_token": token,
                                 @"email": email,
                                 @"password": passwd};
    return [self handleAccessTokenWithSignal:[APINetwork rac_POST:@"fb-login/password" parameters:parameters] is_guest:0];
}

+ (RACSignal *)logout
{
    return [[[[[APINetwork rac_DELETE:@"logout" parameters:nil] handleInvalidToken:^(NSError * _Nonnull error) {
        [AccessToken setCurrentAccessToken:nil];
    } autoAlert:NO] mapReplace:nil]
             catch:^RACSignal * _Nonnull(NSError * _Nonnull error) {
                 if (error.HTTPResponse && error.HTTPResponse.statusCode / 100 == 4)
                 {
                     return [RACSignal return:nil];
                 }
                 return [RACSignal error:error];
             }] doNext:^(id _Nullable x) {
                 [AccessToken setCurrentAccessToken:nil];
                 [Profile setCurrentProfile:nil];
             }];
}

@end
